package config

import (
	"chainproxy/common"
	"fmt"
	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
	"strings"
	"time"
)

type Config struct {
	Name string
}

var configMap map[string]interface{}

func init() {
	c := Config{
		Name: common.ConfigFileName,
	}
	// 初始化配置文件
	if err := c.initConfig(); err != nil {
		panic(err)
	}

	c.watchConfig()
}

func (c *Config) initConfig() error {
	if c.Name != "" {
		// 如果指定了配置文件，则解析指定的配置文件
		viper.SetConfigName(c.Name)
	} else {
		// 如果没有指定配置文件，则解析默认的配置文件
		viper.AddConfigPath("conf")
		viper.SetConfigName("config")
	}
	// 设置配置文件格式为json
	viper.SetConfigType("json")
	viper.AddConfigPath("./config")
	// viper解析配置文件
	if err := viper.ReadInConfig(); err != nil {
		return err
	}
	env := viper.GetString("env")
	configMap = viper.GetStringMap(env)
	return nil
}

// 监听配置文件是否改变,用于热更新
func (c *Config) watchConfig() {
	viper.WatchConfig()
	viper.OnConfigChange(func(e fsnotify.Event) {
		fmt.Printf("Config file changed: %s\n", e.Name)
		env := viper.GetString("env")
		configMap = viper.GetStringMap(env)
	})
}

func GetString(key string) string {
	v, ok := configMap[key].(string)
	if ok{
		return v
	}
	fmt.Println("The value of the key is not of type string, ", key)
	return ""
}

func GetInt(key string) int {
	v, ok := configMap[key].(float64)
	if ok{
		return int(v)
	}
	fmt.Println("The value of the key is not of type int, ", key)
	return 0
}

func GetUint(key string) uint {
	v, ok := configMap[key].(float64)
	if ok{
		return uint(v)
	}
	fmt.Println("The value of the key is not of type uint, ", key)
	return 0
}

func GetDuration(key string) (d time.Duration) {
	s := GetString(key)
	if s == ""{
		return
	}
	if strings.ContainsAny(s, "nsuµmh") {
		d, _ = time.ParseDuration(s)
	} else {
		d, _ = time.ParseDuration(s + "ns")
	}
	return
}

func GetBool(key string) bool {
	v, ok := configMap[key].(bool)
	if ok{
		return v
	}
	fmt.Println("The value of the key is not of type bool, ", key)
	return false
}

func GetSlice(key string) (s []string) {
	v, ok := configMap[key].([]interface{})
	if !ok{
		fmt.Println("The value of the key is not of type []string, ", key)
		return
	}
	for i:=0;i<len(v);i++{
		up,_ := v[i].(string)
		s = append(s, up)
	}
	return
}